/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.panopset.flywheel;

import java.io.IOException;
import static com.panopset.Util.*;

import java.io.File;
import java.io.StringWriter;
import java.util.Date;
import java.util.Vector;

/**
 * If a report directory has been specified in the reserved property value
 * <b>com.panopset.flywheel.reports</b>, this class will be used during
 * script execution to prepare reports that show the template structure in
 * html format.
 *
 * @author Karl Dinwiddie
 */
public class Report implements ReservedWords {

    private final Flywheel flywheel;
    private final File reportDirectory;
    private final Vector<SourceFile> sourceFiles = new Vector<SourceFile>();
    private final Vector<String[]> templateLinkReplacements = new Vector<String[]>();

    public Report(Flywheel flywheel, File reportDirectory) {
        this.flywheel = flywheel;
        this.reportDirectory = reportDirectory;
        mkdirs(this.reportDirectory);
    }

    private String doReplacements(String s) {
        s = s.replace("<", "&lt;").replace(">","&gt;") + DOS_RTN;
        for (String[] r : templateLinkReplacements) {
            s = s.replace(r[0], r[1]);
        }
        return s;
    }

    public void exec() throws IOException {
        for (SourceFile sf : sourceFiles) {
            String[] s = new String[2];
            s[0] = flywheel.openDirective + flywheel.directive + "t " + sf.relativePath + flywheel.closeDirective;
            s[1] = flywheel.openDirective + flywheel.directive + "t <a href=\"" + DEPTH_CHARGE +
                    sf.relativePath + ".html\">" + sf.relativePath + "</a>" + flywheel.closeDirective;
            if (!templateLinkReplacements.contains(s)) {
                templateLinkReplacements.add(s);
            }
        }
        for (SourceFile sf : sourceFiles) {
            String[] s = new String[2];
            s[0] = flywheel.openDirective + flywheel.directive + "l " + sf.relativePath + flywheel.closeDirective;
            s[1] = flywheel.openDirective + flywheel.directive + "l <a href=\"" + DEPTH_CHARGE +
                    sf.relativePath + ".html\">" + sf.relativePath + "</a>" + flywheel.closeDirective;
            if (!templateLinkReplacements.contains(s)) {
                templateLinkReplacements.add(s);
            }
        }
        Date date = new Date();
        for (SourceFile sf : sourceFiles) {
            StringWriter sw = new StringWriter();
            for (String s : sf.getSourceLines()) {
                sw.append(doReplacements(s));
            }
            String templateFilePath = getCanonicalPath(reportDirectory) + PATH_SEP + "com.panopset.templateReport.txt";
            File templateFile = new File(templateFilePath);
            if (!templateFile.exists()) {
                flywheel.copyPackageResource("/com/panopset/flywheel/templateReport.txt", templateFilePath);
            }
            int depth = sf.getDepth();
            StringWriter depthCharge = new StringWriter();
            for (int i=0; i<depth; i++) {
                depthCharge.append("../");
            }
            Flywheel.Builder b = new Flywheel.Builder().targetDirectory(reportDirectory).file(templateFile)
                    .map("fileName", sf.relativePath + ".html")
                    .map("currentFileName", sf.relativePath)
                    .map("topFile", flywheel.get(FILE))
                    .map("depthCharge", depthCharge.toString())
                    .map("last_modified", com.panopset.Util.LAST_MODIFIED_FORMAT.format(date))
                    .map("content", sw.toString().replace(DEPTH_CHARGE, depthCharge.toString()));
            if (isPopulated(flywheel.reportsHref) && isPopulated(flywheel.reportsHomeLinkTitle)) {
                b.map("home", "<a href=\"" + depthCharge.toString() + flywheel.reportsHref + "\">" + flywheel.reportsHomeLinkTitle + "</a>");
            }
            b.construct().exec();
        }
    }

    void addSourceFile(SourceFile sourceFile) {
        for (SourceFile sf : sourceFiles) {
            if (sourceFile.equals(sf)) {
                return;
            }
        }
        sourceFiles.add(sourceFile);
    }
}
